package _40_设计模式._装饰器模式02;

/**
 * 装饰器模式要实现的类
 * Component            Shape
 * AConcreteComponent   Circle
 * BConcreteComponent   Rectangle
 * Decorator            Decorator
 * AConcreteDecorator   RedDecorator
 * BConcreteDecorator   GreenDecorator
 */

// 1. 实现 被装饰器组件 操作
// Component
interface Shape {
    void draw();
}

// 2. 实现 被装饰器组件 的具体实现类
// AConcreteComponent
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个圆形");
    }
}

// BConcreteComponent
class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("画一个方形");
    }
}

// 3. 实现 装饰器
// Decorator
abstract class Decorator implements Shape {
    // 使用 protected，便于子类访问
    protected Shape shape;

    public Decorator(Shape shape) {
        this.shape = shape;
    }

    @Override
    public void draw() {
        shape.draw();
    }

}

// 4. 实现 具体功能的 装饰器
// AConcreteDecorator
class RedDecorator extends Decorator {

    public RedDecorator(Shape shape) {
        super(shape);
    }

    @Override
    public void draw() {
        // 可以在原功能之前增加功能
        // 调用原方法
        shape.draw();
        // 可以在原功能之后增加功能
        setRed(shape);
    }

    // 装饰器功能：设置红色
    public void setRed(Shape shape) {
        System.out.println("设置红色");
    }
}

// BConcreteDecorator
class GreenDecorator extends Decorator {

    public GreenDecorator(Shape shape) {
        super(shape);
    }

    @Override
    public void draw() {
        shape.draw();
        setRed(shape);
    }

    // 装饰器功能：设置绿色
    public void setRed(Shape shape) {
        System.out.println("设置绿色");
    }
}

// 5. 在客户端中使用 装饰器
public class DecoratorTest02 {
    public static void main(String[] args) {
        // 1. 标准的使用过程，画一个 圆，红色的
        // 创建一个 被装饰器组件圆
        Circle circle = new Circle();
        // 创建一个 具体的装饰器红色
        RedDecorator redDecorator = new RedDecorator(circle);
        // 执行方法
        redDecorator.draw();

        // 2. 画一个 方形，红色的
        new RedDecorator(new Rectangle()).draw();

        // 3. 画一个 方形，绿色的
        new GreenDecorator(new Rectangle()).draw();

        // 4. 画一个 方形，红绿色的（可以组合多个装饰功能）
        new RedDecorator(new GreenDecorator(new Rectangle())).draw();

        // 总结 可以看出，使用装饰器，可以对原来的类 动态添加、删除装饰功能
    }
}